﻿using Dapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using S.Authorization.Common.Dto;
using S.Authorization.Common.RabbitMQ;
using S.Authorization.Domain.Model.Authority;
using S.Authorization.Domain.Redis;
using S.Authorization.Domain.SqlServer;
using S.Authorization.Infrastructure.Interface.RoleMenu;
using System.Text;
using static S.Authorization.Common.RabbitMQ.RabbitHelper;

namespace S.Authorization.Infrastructure.Impl.RoleMenu
{
    /// <summary>
    /// 设置角色的权限
    /// </summary>
    public class RoleMenuRepository : BaseRepository<RoleMenuList>, IRoleMenuRepository
    {
        private readonly MyRedisHelper myRedisHelper;
        private readonly IConfiguration configuration;

        public RoleMenuRepository(SqlDbContext db,MyRedisHelper myRedisHelper, IConfiguration configuration) : base(db)
        {
            this.myRedisHelper = myRedisHelper;
            this.configuration = configuration;
        }

        /// <summary>
        /// 设置用户的角色权限
        /// </summary>
        /// <param name="models">添加的数据</param>
        /// <returns>返回受影响的行数</returns>
        public async Task<int> AddRangeRoleMenuAsync(List<FeatureMenuRole> models)
        {
            //延迟队列
            var tran=db.Database.BeginTransaction();
            int isOk = 0;
            try
            {
                //RabbitHelper.rabbitmq.Send(MessageDataMq.exchangeName, MessageDataMq.routingKey, MessageDataMq.queueName, models, MessageDataMq.exchangeType);
                //// 链接字符串
                //var connection = RabbitMQHelper.GetConnection();
                //{
                //    //创建信道
                //    var channel = connection.CreateModel();
                //    {
                //        string queueName = MessageDataMq.queueName;
                //        //创建队列
                //        channel.QueueDeclare(queueName, durable: true, exclusive: false, autoDelete: false, arguments: null);
                //        var consumer = new EventingBasicConsumer(channel);
                //        channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
                //        consumer.Received += async (model, ea) =>
                //        {
                //            // 处理接收到的消息
                //            var message = Encoding.UTF8.GetString(ea.Body.ToArray());
                //            Console.WriteLine($"消费消息:{message}");
                //            // 将消息转换为需要处理的数据对象
                //            var receivedData = JsonConvert.DeserializeObject<List<FeatureMenuRole>>(message);
                // 调用其他方法来执行数据库操作和其他逻辑
                //int isOk = 0;
                // 先查询
                //int[] ids = receivedData.Select(x => x.RoleId).ToArray();
                int[] ids = models.Select(x => x.RoleId).ToArray();
                List<FeatureMenuRole> featureRoleMenuList = db.FeatureMenuRole.Where(x => ids.Contains(x.RoleId)).ToList();
                            if (featureRoleMenuList.Count > 0)
                            {
                                // 如果有数据，删除对应角色的数据
                                db.FeatureMenuRole.RemoveRange(featureRoleMenuList);
                                isOk += await  db.SaveChangesAsync();
                            }
                            List<FeatureMenuRole> updatedModels = new List<FeatureMenuRole>();
                            // 遍历接收到的数据列表中的每个对象
                            foreach (var model in models)
                            {
                                // 判断MenuId是否为1
                                if (model.FeatureId != 23 && model.MenuId != 0)
                                {
                                    // 创建一个新的FeatureMenuRole对象，将RoleId、MenuId和FeatureId设置为1、1和23
                                    var updatedModel = new FeatureMenuRole
                                    {
                                        RoleId = model.RoleId,
                                        MenuId = model.MenuId,
                                        FeatureId = 23
                                    };
                                    // 将新的对象添加到更新后的列表中
                                    updatedModels.Add(updatedModel);
                                }
                                // 将原始的model对象也添加到更新后的列表中
                                updatedModels.Add(model);
                            }
                            // 批量添加
                            db.FeatureMenuRole.AddRangeAsync(updatedModels);
                            isOk+=await db.SaveChangesAsync();
                           
                            //channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
                       //};
                        //channel.BasicConsume(queueName, autoAck: false, consumer);
                   // }

                //}
                tran.CommitAsync();
                return isOk;
             }
            catch (Exception)
            {
                //await CompensateAsync(models);
                tran.RollbackAsync();
                throw;
            }
        }
        /// <summary>
        /// 补偿操作 
        /// </summary>
        /// <param name="models"></param>
        /// <returns></returns>
        private async Task CompensateAsync(List<FeatureMenuRole> models)
        {
            try
            {
                // 执行补偿操作，可以撤销之前的操作或执行其他纠正操作
                // ...
                // 发送补偿消息到消息队列，通知其他组件进行相应的补偿处理
                RabbitHelper.rabbitmq.SendAsync(MessageDataMq.exchangeName, MessageDataMq.routingKey, MessageDataMq.queueName, models, MessageDataMq.exchangeType);
                // 记录补偿操作的日志等信息
                // ...

            }
            catch (Exception ex)
            {
                // 处理补偿操作错误的情况
                // ...
                Console.WriteLine(ex.ToString());
                throw; // 可以选择抛出异常以通知上层调用者
            }
        }
        /// <summary>
        /// 递归显示菜单导航
        /// </summary>
        /// <returns></returns>
        private List<MenuItemDto> GetMenuItem(int pId, List<MenuAndOperationDto> menuListByUId)//
        {
            List<MenuAndOperationDto> menuList = menuListByUId.Where(x => x.MenuList.PId == pId).ToList();
            List<MenuItemDto> list = menuList.Select( x => new MenuItemDto
            {
                value = x.MenuList.MenuId,
                title = x.MenuList.MenuName,
                path = x.MenuList.Path,
                icon = x.MenuList.MenuIcon,
                operationList=x.OperationList,
                children = GetMenuItem(x.MenuList.MenuId, menuListByUId).Count == 0 ? null : GetMenuItem(x.MenuList.MenuId, menuListByUId),
            }).ToList();
            return list;
        }
        /// <summary>
        /// 显示当前用户下的菜单
        /// </summary>
        /// <param name="userId">当前用户登录ID</param>
        /// <returns>返回该用户下的权限菜单</returns>
        public List<MenuItemDto> GetMenuList(int pId, int userId)
        {
            //先从redis中查询，如果没有数据，从数据库查询，添加到redis中
            List<MenuItemDto> redisList = new List<MenuItemDto>();
            var a= myRedisHelper.HMGet("userMenu", userId.ToString()).ToList();
            //如果redis没有
            if(a.Count == 1 && a[0] == null)//从数据库查询的数据存到redis
            {
                //查询用户下的所有菜单  和菜单对应的功能 
                List<MenuAndOperationDto> menuListByUId = (from u in db.UsersModel//用户表
                                                           join ru in db.UserRole //用户角色表
                                                           on u.UserId equals ru.UserId
                                                           join r in db.RoleModel  //角色表
                                                           on ru.RoleId equals r.RoleId
                                                           join fmr in db.FeatureMenuRole  //角色菜单功能表
                                                           on r.RoleId equals fmr.RoleId
                                                           join m in db.MenuList  //菜单
                                                           on fmr.MenuId equals m.MenuId
                                                           where u.IsDel == false && u.UserId == userId
                                                           select new MenuAndOperationDto()
                                                           {
                                                               MenuList = m,
                                                               OperationList = (from om in db.FeatureMenuRole
                                                                                join o in db.Operation
                                                                                on om.FeatureId equals o.OperationId
                                                                                where om.MenuId == m.MenuId
                                                                                select o).ToList()
                                                           }).GroupBy(dto => dto.MenuList.MenuId)
                                                  .Select(group => group.First()).ToList();
                List<MenuItemDto> list = GetMenuItem(pId, menuListByUId);
                myRedisHelper.HMSet("userMenu", userId.ToString(), list.ToArray());
            }
            var b = myRedisHelper.HMGet("userMenu", userId.ToString()).ToList();

            foreach (var str in b)
            {
                var menuItem = JsonConvert.DeserializeObject<List<MenuItemDto>>(str);
                redisList.AddRange(menuItem);
            }

            return redisList;
        }




        /// <summary>
        /// 获取每个菜单下的所有功能
        /// </summary>
        /// <param name="menuId">菜单Id</param>
        /// <returns>返回查询后的数据</returns>
        public async Task<List<MenuItemDto>> GetMenuAndOperation(int? menuId)
        {
            //List<MenuList> menuList=db.MenuList.Where(x=> (menuId==0 || x.MenuId==menuId)).ToList();

            List<MenuAndOperationDto> menuListByUId = (from m in db.MenuList
                                              where menuId == 0 || m.MenuId == menuId
                                              select new MenuAndOperationDto()
                                              {
                                                  MenuList = m,
                                                  OperationList = (from om in db.FunctionOperation
                                                                   join o in db.Operation
                                                                   on om.OperationId equals o.OperationId
                                                                   where om.MenuId == m.MenuId
                                                                   select o).ToList(),
                                              }).ToList();
            List<MenuItemDto> list= GetMenuItem(0, menuListByUId);
           return await Task.FromResult(list);
        }
        //递归当前传过来的Id的子级，如果有子级的数据，就判断是否要连同子级的删除，点击确定后，前端
        /// <summary>
        /// 显示当前用户下的菜单
        /// </summary>
        /// <param name="userId">当前用户登录ID</param>
        /// <returns>返回该用户下的权限菜单</returns>
        List<int> IRoleMenuRepository.GetMenuIdByPId(int pId,int roleId)
        {
            //查询用户下的所有菜单  和菜单对应的功能 
            List<MenuAndOperationDto> menuListByUId =db.MenuList.Where(x=>x.MenuId==pId || x.PId==pId).Select(x=>new MenuAndOperationDto
            {
                MenuList=x,
                OperationList=null
            }).ToList();
            List<MenuItemDto> list = GetMenuItem(pId, menuListByUId);
            int[] mIds=list.Select(x=>x.value).ToArray();
            List<int> fmrList = db.FeatureMenuRole.Where(x => mIds.Contains(x.MenuId) && x.RoleId == roleId).Select(x=>x.MenuId).ToList();
            return fmrList;
        }


        /// <summary>
        /// 显示菜单功能角色表
        /// </summary>
        /// <param name="menuId">菜单ID</param>
        /// <returns>返回菜单ID，菜单Name，角色ID，角色Name，功能名称</returns>
        public async Task<List<FeatureMenuRoleDto>> GetFeatureMenuRole(int menuId)
        {
            string connectionString = configuration.GetValue<string>("ConnectionStrings");

            using (var connection = new SqlConnection(connectionString))
            {
                try
                {
                    connection.Open();

                    StringBuilder sqlQuery = new StringBuilder();
                    sqlQuery.Append(@"
                        SELECT m.MenuId, m.MenuName, r.RoleId, r.RoleName, STRING_AGG(o.OperationName, ', ') AS OperationName
                        FROM dbo.FeatureMenuRole fmr
                        INNER JOIN dbo.Operation o ON fmr.FeatureId = o.OperationId
                        INNER JOIN dbo.MenuList m ON fmr.MenuId = m.MenuId
                        INNER JOIN dbo.RoleModel r ON fmr.RoleId = r.RoleId
                        WHERE 1=1  ");

                    if (menuId > 0)
                    {
                        sqlQuery.Append(" AND m.MenuId=@MenuId");
                    }

                    sqlQuery.Append(" GROUP BY m.MenuId, m.MenuName, r.RoleId, r.RoleName;");


                    var result = connection.Query<FeatureMenuRoleDto>(sqlQuery.ToString(), new { @MenuId = menuId }).AsList();

                    return await Task.FromResult(result);
                }
                catch (Exception)
                {
                    throw;
                }
                finally {
                    connection.Close();
                }

              
            }
        }


        /// <summary>
        /// 删除菜单功能角色表
        /// </summary>
        /// <param name="menuId">菜单ID</param>
        /// <param name="roleId">角色ID</param>
        /// <returns></returns>
        public async Task<bool> DeleteRangeFeatureMenuRole(string menuId, string roleId)
        {
            int[] mIds = menuId.Split(',').Select(int.Parse).ToArray();
            int[]rIds = roleId.Split(',').Select(int.Parse).ToArray();
            List<FeatureMenuRole> featureMenuRoles=db.FeatureMenuRole.Where(x=> mIds.Contains(x.MenuId) && rIds.Contains(x.RoleId)).ToList();
            db.FeatureMenuRole.RemoveRange(featureMenuRoles);
            return await db.SaveChangesAsync() > 0;
        }

        /// <summary>
        /// 菜单表---递归  通过子级ID查询父级数据
        /// </summary>
        /// <param name="mIds">子级ID</param>
        /// <param name="menuLists">查询的数据</param>
        private void GetMenuAllPIdByMId(int[] mIds,ref List<MenuList> menuLists)
        {

            List<MenuList> list=db.MenuList.Where(x=>mIds.Contains(x.MenuId)).ToList();
            if (list != null)
            {
                foreach (var x in list)
                {
                    MenuList menu = new MenuList
                    {
                        MenuId = x.MenuId,
                        MenuName = x.MenuName,
                        Path = x.Path,
                        PId = x.PId,
                        MenuIcon = x.MenuIcon,
                    };
                    menuLists.Add(menu);
                    int[] parentIds = new int[] { x.PId }; // 将当前菜单项的PId转换为int[]
                    GetMenuAllPIdByMId(parentIds, ref menuLists); // 递归调用，传入PId作为目标菜单项ID集合
                }
            }
        }

        /// <summary>
        /// 菜单表--根据MId获取PId
        /// </summary>
        /// <param name="mIds">主键Id</param>
        /// <returns>返回该数据的父级</returns>
        public async Task<List<int>> GetMenuPIdByMId(string mIds)
        {
            List<MenuList> list = new List<MenuList>();
            //传过来的子级ID
            int[] ids = mIds.Split(',').Select(int.Parse).ToArray();
            GetMenuAllPIdByMId(ids, ref list);

            List<int> pIds = list.Select(x => x.PId).Where(id => id != 0).Except(ids).ToList();

            return pIds;
        }

      
    }
}
